package gl.android.drag.fragmentdragback;

import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

/**
 * Created by Flavien Laurent (flavienlaurent.com) on 23/08/13.
 */
public class DragLayout extends FrameLayout {
	public interface DragListenter {
		public void onDragFinish();
	}

	DragListenter mDragListenter;

	public void setDragListenter(DragListenter mDragListenter) {
		this.mDragListenter = mDragListenter;
	}

	private final ViewDragHelper mDragHelper;
	private boolean mDragEdge = true;
	boolean mDragVertical;

	public DragLayout(Context context) {
		this(context, null);
	}

	public DragLayout(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public DragLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		mDragHelper = ViewDragHelper.create(this, 1f, new DragHelperCallback());
	}

	private View mDragView;

	@Override
	protected void onAttachedToWindow() {
		super.onAttachedToWindow();
		DisplayMetrics mDisplayMetrics = new DisplayMetrics();
		getDisplay().getMetrics(mDisplayMetrics);
		mDragHelper.setEdgeSize((int) TypedValue.applyDimension(
				TypedValue.COMPLEX_UNIT_DIP, 160, mDisplayMetrics));
		mDragView = getChildAt(0);

	}

	public void setDragEdge(boolean dragEdge) {
		mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_RIGHT);
		mDragEdge = dragEdge;
	}

	private class DragHelperCallback extends ViewDragHelper.Callback {

		@Override
		public boolean tryCaptureView(View child, int pointerId) {
			return child == mDragView;
		}

		@Override
		public void onViewPositionChanged(View changedView, int left, int top,
				int dx, int dy) {
			invalidate();
			System.out.println("onViewPositionChanged" + left);
			if (getEdgeFinshSize() == left) {
				if (mDragListenter != null) {
					mDragListenter.onDragFinish();
				}
			}
		}

		@Override
		public void onViewCaptured(View capturedChild, int activePointerId) {
			super.onViewCaptured(capturedChild, activePointerId);
		}

		@Override
		public void onViewReleased(View releasedChild, float xvel, float yvel) {
			super.onViewReleased(releasedChild, xvel, yvel);
		}

		@Override
		public void onEdgeTouched(int edgeFlags, int pointerId) {
			super.onEdgeTouched(edgeFlags, pointerId);
		}

		@Override
		public void onEdgeDragStarted(int edgeFlags, int pointerId) {
			if (mDragEdge) {
				mDragHelper.captureChildView(mDragView, pointerId);
			}
			System.out.println("onEdgeDragStarted" + (mDragEdge));
		}

		@Override
		public int clampViewPositionVertical(View child, int top, int dy) {

			if (mDragVertical) {
				return top;
			}
			return super.clampViewPositionVertical(child, top, dy);
		}

		@Override
		public int clampViewPositionHorizontal(View child, int left, int dx) {
			if (mDragEdge) {
				// final int leftBound = getPaddingLeft();
				// final int rightBound = getWidth() /*-
				// mDragView1.getWidth()*/;

				// final int newLeft = leftBound;
				// final int newLeft = Math.min(Math.max(left, leftBound),
				// rightBound);
				return left;
				// return newLeft;
			}

			return super.clampViewPositionHorizontal(child, left, dx);
		}

	}

	private int getEdgeFinshSize() {
		return getWidth() * -1;
	}

	boolean isIntercept = false;

	private float mInitialMotionX;

	private float mInitialMotionY;

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		try {
			final int action = MotionEventCompat.getActionMasked(ev);
			if (action == MotionEvent.ACTION_CANCEL
					|| action == MotionEvent.ACTION_UP) {
				mDragHelper.cancel();
				return false;
			}
			return mDragHelper.shouldInterceptTouchEvent(ev);
		} catch (Exception e) {
		}
		return false;
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		return super.dispatchTouchEvent(ev);
	}

	@Override
	protected void onAnimationEnd() {
		super.onAnimationEnd();
		if (mDragListenter != null) {
			mDragListenter.onDragFinish();
		}
	}

	@Override
	public void computeScroll() {
		if (mDragHelper.continueSettling(true)) {
			ViewCompat.postInvalidateOnAnimation(this);
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		final int action = ev.getAction();
		final float x = ev.getX();
		final float y = ev.getY();
		mDragHelper.processTouchEvent(ev);
		switch (action & MotionEventCompat.ACTION_MASK) {
		case MotionEvent.ACTION_DOWN:
			mInitialMotionX = x;
			mInitialMotionY = y;
			break;

		case MotionEvent.ACTION_UP:
			final float dx = x - mInitialMotionX;
			final float dy = y - mInitialMotionY;
			final int slop = mDragHelper.getTouchSlop();
			boolean isTap = (dx * dx + dy * dy) < slop * slop;
			// boolean isValidDrag = false;
			// if (Math.abs(dx) >= getWidth() / 2
			// || Math.abs(dy) >= getHeight() / 2) {
			// isValidDrag = true;
			// }
			if (!isTap) {
				if (dx < 0 && Math.abs(dx) > getWidth() / 2) {
					if (mDragHelper.smoothSlideViewTo(mDragView,
							getEdgeFinshSize(), 0)) {// finish
						ViewCompat.postInvalidateOnAnimation(this);
						return true;
					}
				} else {// restore
					if (mDragHelper.smoothSlideViewTo(mDragView, 0, 0)) {
						ViewCompat.postInvalidateOnAnimation(this);
						return true;
					}
				}
			}

			break;

		}

		return true;
	}

	public void setDragView(ViewGroup view) {
		removeAllViews();
		addView(view);
		mDragView = view;
	}

}
